package com.itlong.cloud.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.app.AppFaceRecognitionPaymentDTO;
import com.itlong.cloud.POJO.DTO.app.AppTouristDTO;
import com.itlong.cloud.POJO.DTO.app.AppUserRegisterDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.AppLoginErrorCacheVO;
import com.itlong.cloud.POJO.VO.app.AppUserCacheVO;
import com.itlong.cloud.POJO.VO.app.AppUserOwnProjectVO;
import com.itlong.cloud.POJO.VO.property.PropertyPaymentVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.app.dao.IAppRegisterDao;
import com.itlong.cloud.app.service.IAppRegisterService;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode_en.AppErrorCodeEnumEN;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.location.LocationUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *     APP的登录与注册板块服务层实现类
 * </desc>
 *
 * @createDate 2017/9/21
 */
@Service
@RefreshScope
public class AppRegisterServiceImpl implements IAppRegisterService{
    private static final Logger LOG = LoggerFactory.getLogger(AppRegisterServiceImpl.class);

    @Autowired
    private RedisService<AppUserCacheVO> redisService;

    //Redis工具接口类
    @Autowired
    private RedisService<AppLoginErrorCacheVO> loginErrorRedisService;

    @Autowired
    private IAppRegisterDao iAppRegisterDao;

    @Autowired
    private MessageSender messageSender;

    @Value("${" + PlatformConstants.APP_USER_TOKEN_KEY + "}")
    String appDesKey;

    @Value("${" + PlatformConstants.COMMUNITY_SCENE_ID + "}")
    String communitySceneId;

    @Value("${" + PlatformConstants.PARK_SCENE_ID + "}")
    String parkScene;

    @Value("${" + PlatformConstants.HOTEL_SCENE_ID + "}")
    String hotelSceneId;

    @Value("${" + PlatformConstants.HOSPITAL_SCENE_ID + "}")
    String hospitalSceneId;

    String userIdSeparator = "_";
    String dateFormatStr = "yyyy-MM-dd HH:mm:ss";

    /**
     * <desc>
     *     根据手机号检测APP当前用户是否已存在
     * </desc>
     *
     * @param phoneNo  手机号
     * @return true-是，false-否
     * @author cuiduanwu
     * @createDate 2017/09/21
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean checkUserByPhoneNo(String phoneNo){

        return  iAppRegisterDao.checkUserByPhoneNo(phoneNo)>0?true:false;
    }
    /**
     * <desc>
     *     根据手机号查询用户
     * </desc>
     * @param phoneNo
     * @return
     * @author cuiduanwu
     * @createDate 2017/09/21
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public AppUserInfoPO getUserByPhoneNo(String phoneNo){
        if (StringUtils.isBlank(phoneNo)){
            return  null;
        }
        return  iAppRegisterDao.getUserByPhoneNo(phoneNo);
    }

    /**
     * <desc>
     *     根据邮箱查询用户
     * </desc>
     * @param email
     * @return
     * @author shengen.T
     * @createDate 2017/09/21
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)
    public AppUserInfoPO getUserByEmail(String email){
        if (StringUtils.isBlank(email)){
            return  null;
        }
        return  iAppRegisterDao.getUserByEmail(email);
    }

    /**
     * <desc>
     *     APP端用户注册提交验证
     * </desc>
     *
     * @param appUserRegisterDTO
     * @return
     * * @author cuiduanwu
     * @createDate 2017/09/21
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean registerUser(AppUserRegisterDTO appUserRegisterDTO) throws  Exception{
        try {
            AppUserCacheVO appUserCacheVO = redisService.getObject(RedisConstant.APP_LOGIN+appUserRegisterDTO.getUserId(),AppUserCacheVO.class);
            if (appUserCacheVO != null&&appUserCacheVO.getToken().equals(appUserRegisterDTO.getToken())){
                AppUserInfoPO appUserInfoPO;
                AppUserInfoPO currentUser;
                if (LanguageTypeEnum.CHINESE.getLanguage().equals(appUserRegisterDTO.getLanguage())){  //手机号
                    appUserInfoPO = new AppUserInfoPO(appUserCacheVO.getUserId(),appUserRegisterDTO.getUserName(),appUserRegisterDTO.getNickName(),
                            appUserRegisterDTO.getPswd(),appUserCacheVO.getPhoneNo(),appUserCacheVO.getToken(), null);
                    appUserInfoPO.setCreateTime(new Date());
                    appUserInfoPO.setUpdateTime(new Date());
                    appUserInfoPO.setPhoneUnique(appUserRegisterDTO.getUuid());
                    currentUser = iAppRegisterDao.getUserByPhoneNo(appUserCacheVO.getPhoneNo());
                }else { //邮箱
                    appUserInfoPO = new AppUserInfoPO(appUserCacheVO.getUserId(),appUserRegisterDTO.getUserName(),appUserRegisterDTO.getNickName(),
                            appUserRegisterDTO.getPswd(),"",Integer.parseInt(appUserRegisterDTO.getSex()),appUserCacheVO.getToken());
                    appUserInfoPO.setEmail(appUserCacheVO.getPhoneNo());
                    appUserInfoPO.setCreateTime(new Date());
                    appUserInfoPO.setUpdateTime(new Date());
                    appUserInfoPO.setPhoneUnique(appUserRegisterDTO.getUuid());
                    currentUser = iAppRegisterDao.getUserByEmail(appUserCacheVO.getPhoneNo());
                }
                appUserInfoPO.setIsOnline(1);
                boolean flag;
                if (currentUser != null){
                    flag = iAppRegisterDao.updateByPoNotNull(appUserInfoPO)>0?true:false;
                }else {
                    flag = iAppRegisterDao.save(SqlUtil.durableData(appUserInfoPO,PlatformConstants.TABLE_SAVE))>0?true:false;
                    if (flag){
                        redisService.set(RedisConstant.APP_LOGIN+appUserInfoPO.getUserId(), RedisConstant.APP_USER_TOKEN_TIME,appUserCacheVO);

                        //TODO 此段代码后期再开放 当APP用户注册后需向发送消息队列，创建灵云快智账号并保存
                        /*Map<String,Object> paramsMap=new HashMap<>();
                        paramsMap.put("userId",appUserInfoPO.getUserId());
                        paramsMap.put("mobile ",appUserInfoPO.getPhoneNum());
                        messageSender.send(RabbitMQConstant.RABBITMQ_USER_CREATE_LYKZ_ACCOUNT_QUEUE, JSON.toJSONString(paramsMap),
                                RabbitMQConstant.RABBITMQ_USER_EXCHANGE, RabbitMQConstant.RABBITMQ_USER_CREATE_LYKZ_ACCOUNT_KEY);*/

                        //针对物业预授权的用户及邀请家人的用户激活后通知云对讲设备
                        List<AppUserOwnProjectVO>  userOwnProjectList = this.getUserOwnProjectsInfo(appUserCacheVO.getUserId(),"-1");
                        if (userOwnProjectList != null&&userOwnProjectList.size()>0){
                            for (AppUserOwnProjectVO appUserOwnProjectVO:userOwnProjectList){
                                JSONObject js = new JSONObject();
                                js.put("projectId",appUserOwnProjectVO.getProjectId());
                                js.put("userId",appUserCacheVO.getUserId());
                                DeviceBusinessChangeLogPO deviceBusinessChangeLogPO = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT,js,appUserOwnProjectVO.getProjectId());
                                List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
                                changeLogPOS.add(deviceBusinessChangeLogPO);
                                if (changeLogPOS != null && !changeLogPOS.isEmpty()) {
                                    JSONObject datajs = new JSONObject();
                                    datajs.put("data",changeLogPOS);
                                    messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                                            JSON.toJSONString(datajs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                                            RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                                }
                            }
                        }
                    }
                }
                return  flag;
            }else {
                LOG.info("【APP_注册与登录_注册提交】TOKEN验证不一致");
                return  false;
            }
        }catch (Exception e){
            throw new DataAccessException("【APP_注册与登录_注册提交】保存或更新用户信息失败",e);
        }

    }

    /**
     * <desc>
     *     APP端根据手机号更新用户密码
     * </desc>
     *
     * @param phoneNo   手机号
     * @param pswd 新密码
     * @return
     * @throws Exception
     * @author cuiduanwu
     * @createDate 2017/09/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean updateUserPswdByPhone(String phoneNo,String pswd) throws  Exception{
        try {
            Map<String,String> params = new HashMap<>();
            params.put("phoneNo",phoneNo);
            params.put("pswd",pswd);
            Integer result = iAppRegisterDao.updateUserPswdByPhone(params);
            return true;
        }catch (Exception e){
            LOG.error("【APP_注册登录_更新用户密码】updateUserPswdByPhone失败",e);
            return  false;
        }
    }
    /**
     * <desc>
     *     APP端根据邮箱更新用户密码
     * </desc>
     *
     * @param email  用户邮箱
     * @param pswd  新密码
     * @return
     * @throws Exception
     * @author cuiduanwu
     * @createDate 2017/09/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean updateUserPswdByEmail(String email,String pswd) throws  Exception{
        try {
            Map<String,String> params = new HashMap<>();
            params.put("email",email);
            params.put("pswd",pswd);
            Integer result = iAppRegisterDao.updateUserPswdByEmail(params);
            return true;
        }catch (Exception e){
            LOG.error("【APP_注册登录_更新用户密码】updateUserPswdByEmail失败",e);
            return  false;
        }
    }

    /**
     * <desc>
     *     APP端用户登录
     * </desc>
     *
     * @param phoneNo
     * @param pswd
     * @return AppUserCacheVO
     * @throws Exception
     * @author cuiduanwu
     * @createDate 2017/09/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public  AppUserCacheVO appUserLogin(String phoneNo,String pswd,String loginDevice) throws  Exception{
        AppUserCacheVO appUserCacheVO = null;
        Map<String,String> params = new HashMap<>();
        params.put("phoneNo",phoneNo);
        params.put("pswd",pswd);
        AppUserInfoPO appUserInfoPO = iAppRegisterDao.appUserLogin(params);
        if (appUserInfoPO != null&&appUserInfoPO.getPassword().equals(pswd)){
            AppUserInfoPO currentUser = new AppUserInfoPO(appUserInfoPO.getUserId());
            currentUser.setIsOnline(1);
            currentUser.setLoginDevice(Integer.parseInt(loginDevice));
            iAppRegisterDao.updateByPoNotNull(currentUser);

            appUserCacheVO = new AppUserCacheVO();
            appUserCacheVO.setId(appUserInfoPO.getId());
            appUserCacheVO.setLoginDevice(loginDevice);
            appUserCacheVO.setUserId(appUserInfoPO.getUserId());
            appUserCacheVO.setPhotoUrl(appUserInfoPO.getIcon());
            appUserCacheVO.setNickName(appUserInfoPO.getNickName());
            appUserCacheVO.setUserName(appUserInfoPO.getRealName());
            appUserCacheVO.setPhoneNo(phoneNo);
            appUserCacheVO.setToken(appUserInfoPO.getToken());
            appUserCacheVO.setSex(appUserInfoPO.getGender()+"");
            appUserCacheVO.setCurrentProjectId(appUserInfoPO.getCurrentProjectId());
            appUserCacheVO.setCurrentProjectName(appUserInfoPO.getCurrentProjectName());
            appUserCacheVO.setStatus(appUserInfoPO.getStatus());
            // 查询用户第三方账号token信息
            CloudIntercomAccountInfoPO clientAccount = iAppRegisterDao.getClientAccount(appUserInfoPO.getCloudIntercomAccountId());
            if (clientAccount != null) {
                appUserCacheVO.setClientToken(clientAccount.getToken());
            }
            redisService.set(RedisConstant.APP_LOGIN+appUserCacheVO.getUserId(),RedisConstant.APP_USER_TOKEN_TIME,appUserCacheVO);
        }
        return  appUserCacheVO;
    }
    /**
     * <desc>
     *     APP端邮箱用户登录
     * </desc>
     *
     * @param email
     * @param pswd
     * @return AppUserCacheVO
     * @throws Exception
     * @author cuiduanwu
     * @createDate 2017/12/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public  AppUserCacheVO appUserLoginByEmail(String email,String pswd,String loginDevice) throws  Exception{
        AppUserCacheVO appUserCacheVO = null;
        Map<String,String> params = new HashMap<>();
        params.put("email",email);
        params.put("pswd",pswd);
        AppUserInfoPO appUserInfoPO = iAppRegisterDao.appUserLoginByEmail(params);
        if (appUserInfoPO != null&&StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty(appUserInfoPO.getPassword(),pswd)){
            AppUserInfoPO currentUser = new AppUserInfoPO(appUserInfoPO.getUserId());
            currentUser.setIsOnline(1);
            currentUser.setLoginDevice(Integer.parseInt(loginDevice));
            iAppRegisterDao.updateByPoNotNull(currentUser);

            appUserCacheVO = new AppUserCacheVO();
            appUserCacheVO.setId(appUserInfoPO.getId());
            appUserCacheVO.setLoginDevice(loginDevice);
            appUserCacheVO.setUserId(appUserInfoPO.getUserId());
            appUserCacheVO.setPhotoUrl(appUserInfoPO.getIcon());
            appUserCacheVO.setNickName(appUserInfoPO.getNickName());
            appUserCacheVO.setUserName(appUserInfoPO.getRealName());
            appUserCacheVO.setEmail(email);
            appUserCacheVO.setPhoneNo(email);
            appUserCacheVO.setToken(appUserInfoPO.getToken());
            appUserCacheVO.setSex(appUserInfoPO.getGender()+"");
            appUserCacheVO.setCurrentProjectId(appUserInfoPO.getCurrentProjectId());
            appUserCacheVO.setCurrentProjectName(appUserInfoPO.getCurrentProjectName());
            appUserCacheVO.setStatus(appUserInfoPO.getStatus());
            // 查询用户第三方账号token信息
            CloudIntercomAccountInfoPO clientAccount = iAppRegisterDao.getClientAccount(appUserInfoPO.getCloudIntercomAccountId());
            if (clientAccount != null) {
                appUserCacheVO.setClientToken(clientAccount.getToken());
            }
            redisService.set(RedisConstant.APP_LOGIN+appUserCacheVO.getUserId(),RedisConstant.APP_USER_TOKEN_TIME,appUserCacheVO);
        }
        return  appUserCacheVO;
    }

    /**
     * <desc>
     *     APP端登录获取用户项目列表信息
     * </desc>
     *
     * @param userId  用户ID
     * @param deviceType 设备类型 1-安卓系统，2-ios系统
     * @return  APP用户所拥有的项目配置信息的集合
     * @throws Exception
     * @createDate 2017/9/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public List<AppUserOwnProjectVO> getUserOwnProjectsInfo(String userId,String deviceType) throws  Exception{

        List<AppUserOwnProjectVO> userOwnProjectVOList = iAppRegisterDao.getUserOwnProjectsInfo(userId);
        List<AppUserOwnProjectVO> delUserOwnProjectVOList = new ArrayList<>();  //待移除的用户名下项目集合
        Map<String,Object> userprojectmap = new HashMap<>();
        userprojectmap.put("userId",userId);

        boolean isEmailUser = false;
        if (StringUtils.isNotBlank(iAppRegisterDao.getAppUserEmail(userId))){
            isEmailUser = true;//非空则为国际用户
        }

        if (userOwnProjectVOList != null&&userOwnProjectVOList.size()>0){

            for (AppUserOwnProjectVO appUserOwnProjectVO:userOwnProjectVOList){
                Map<String,Object> params = new  HashMap<>();
                params.put("userId",userId);
                //设置项目场景
                Map<String, Integer> sceneMap = this.getSceneTypeMap();
                if (StringUtils.isBlank(appUserOwnProjectVO.getSceneId())){
                    //未选场景,默认返回社区场景
                    appUserOwnProjectVO.setProjectType(SceneTypeEnum.COMMUNITY_SCENE.getType());
                }else if(StringUtils.isNotBlank(appUserOwnProjectVO.getSceneId()) && sceneMap.get(appUserOwnProjectVO.getSceneId())!=null){
                    appUserOwnProjectVO.setProjectType(sceneMap.get(appUserOwnProjectVO.getSceneId()));
                }else {
                    //非4种场景
                    appUserOwnProjectVO.setProjectType(SceneTypeEnum.OTHER_SCENE.getType());
                }
                params.put("projectId",appUserOwnProjectVO.getProjectId());
                Integer userAuthCount = iAppRegisterDao.countUserAttacheInfoInProject(params);
                appUserOwnProjectVO.setOwnerAddress(userAuthCount>0?"1":"0");
                params.put("houserType","1");  //业主身份
                Integer userAddressCount = iAppRegisterDao.countUserAttacheInfoInProject(params);
                appUserOwnProjectVO.setUserAuth(userAddressCount>0?"1":"0");
                //用户项目是否被禁用信息
                if(iAppRegisterDao.checkUserProjectStatus(appUserOwnProjectVO.getProjectId()) > 0){
                    appUserOwnProjectVO.setProjectMessage(
                            String.format(AppErrorCodeEnum.USER_PROJECT_DISABLED.getCodeMsg(), appUserOwnProjectVO.getProjectName(),appUserOwnProjectVO.getCenterPhoneNo() != null ? appUserOwnProjectVO.getCenterPhoneNo() : ""));
                    if (isEmailUser){ //国际版提示
                        appUserOwnProjectVO.setProjectMessage(
                                String.format(AppErrorCodeEnumEN.USER_PROJECT_DISABLED.getCodeMsg(), appUserOwnProjectVO.getCenterPhoneNo() != null ? appUserOwnProjectVO.getCenterPhoneNo() : ""));
                    }
                    appUserOwnProjectVO.setState("1");
                }else {
                    // 用户项目冻结提示信息
                    if (appUserOwnProjectVO.getProjectMessage().equals("0")) {//冻结
                        appUserOwnProjectVO.setProjectMessage(String.format(AppErrorCodeEnum.USER_PROJECT_FREEZE.getCodeMsg(),
                                appUserOwnProjectVO.getProjectName(),
                                appUserOwnProjectVO.getCenterPhoneNo() != null ? appUserOwnProjectVO.getCenterPhoneNo() : ""));
                        if (isEmailUser){ //国际版提示
                            appUserOwnProjectVO.setProjectMessage(String.format(AppErrorCodeEnumEN.USER_PROJECT_FREEZE.getCodeMsg(), appUserOwnProjectVO.getCenterPhoneNo() != null ? appUserOwnProjectVO.getCenterPhoneNo() : ""));
                        }
                        appUserOwnProjectVO.setState("2");
                    }else {
                        appUserOwnProjectVO.setProjectMessage("");
                        appUserOwnProjectVO.setState("0");
                    }
                }
                appUserOwnProjectVO = (AppUserOwnProjectVO)StringHandlerUtil.formatString(appUserOwnProjectVO);

//                2021-4-7多场景适配项目 取消此限制
                userprojectmap.put("projectId",appUserOwnProjectVO.getProjectId());
                Integer userInProjectExistRoom = iAppRegisterDao.countUserRoomInProject(userprojectmap);
                Integer countUserAuthInFloor = iAppRegisterDao.countUserAuthInFloor(userprojectmap);
                Integer countUserAuthInDoor = iAppRegisterDao.countUserAuthInDoor(userprojectmap);
                Integer countUserAuthInCloudDoor = iAppRegisterDao.countUserAuthInCloudDoor(userprojectmap);
                if (!((countUserAuthInFloor+countUserAuthInDoor+countUserAuthInCloudDoor + userInProjectExistRoom)>0)){
                    appUserOwnProjectVO.setDeleteFlag(1);
                }else{
                    appUserOwnProjectVO.setDeleteFlag(0);
                }
            }
        }

        //获取用户有效项目的UI状态
        if((StringUtils.isNotBlank(deviceType)&&("1".equals(deviceType)||"2".equals(deviceType)))&&((userOwnProjectVOList!=null)&&(userOwnProjectVOList.size()>0))){
            String type = "1".equals(deviceType)?"2":"1"; //UI类型中 1是ios 2是安卓所以需要转换
            userOwnProjectVOList.forEach(ownProjectInfo->{
                String tmp = iAppRegisterDao.getUiStatus(ownProjectInfo.getProjectId(),type);
                if(StringUtils.isBlank(tmp) || (!"1".equals(tmp))){
                    ownProjectInfo.setUiStatus("0");
                }else {
                    ownProjectInfo.setUiStatus("1");
                }
            });
        }
        return  userOwnProjectVOList;
    }



    /**
     * <desc>
     *     APP端登录后缓存用户信息
     * </desc>
     * @param appUserCacheVO
     * @return
     * @author cuiduanwu
     * @createDate 2017/9/27
     */
    @Override
    public boolean loginCacheUserVO(AppUserCacheVO appUserCacheVO) throws Exception{
        boolean flag = redisService.set(RedisConstant.APP_LOGIN+appUserCacheVO.getUserId(),RedisConstant.APP_USER_TOKEN_TIME,appUserCacheVO);
        if (flag){
            AppUserInfoPO appUserInfoPO = new AppUserInfoPO(appUserCacheVO.getUserId());
            appUserInfoPO.setUuid(appUserCacheVO.getUuid());
            appUserInfoPO.setUpdateTime(new Date());
            appUserInfoPO.setToken(appUserCacheVO.getToken());
            appUserInfoPO.setIsOnline(1);
            iAppRegisterDao.updateByPoNotNull(appUserInfoPO);

            List<AppUserOwnProjectVO> userOwnProjectList = appUserCacheVO.getProjects();
            if (userOwnProjectList != null&&userOwnProjectList.size()>0){
                for (AppUserOwnProjectVO appUserOwnProjectVO:userOwnProjectList){
                    JSONObject js = new JSONObject();
                    js.put("projectId",appUserOwnProjectVO.getProjectId());
                    js.put("userId",appUserCacheVO.getUserId());
                    DeviceBusinessChangeLogPO deviceBusinessChangeLogPO = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_USER_PROJECT,js,appUserOwnProjectVO.getProjectId());
                    List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
                    changeLogPOS.add(deviceBusinessChangeLogPO);
                    if (changeLogPOS != null && !changeLogPOS.isEmpty()) {
                        JSONObject datajs = new JSONObject();
                        datajs.put("data",changeLogPOS);
                        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                                JSON.toJSONString(datajs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                                RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                    }
                }
            }
        }
        return  flag;
    }

    /**
     * <desc>
     *     根据userId和projectId查询该用户是否欠费
     * </desc>
     * @param projectId 项目编号
     * @param userId 用户Id
     * @return
     * @author Juguang.S
     * @createDate 2019/01/22
     */
    @Override
    public Integer getUserIsForbidden(String projectId, String userId) throws Exception {
        return iAppRegisterDao.getUserIsForbidden(projectId,userId);
    }

    /**
     * <desc>
     *      查询pad用户是否欠费
     * </desc>
     *
     * @param paymentDTO
     * @return
     * @author Jiaqi.X
     * @createDate 2019/06/21
     */
    public Integer getPadUserForbidden(AppFaceRecognitionPaymentDTO paymentDTO){
        Integer userStatus = iAppRegisterDao.getPadUserForbidden(paymentDTO.getProjectId(),paymentDTO.getUId());
        return userStatus;
    }

    /**
     * <desc>
     *      查询pad用户欠费状态
     * </desc>
     *
     * @param paymentDTO
     * @return
     * @author Jiaqi.X
     * @createDate 2019/06/21
     */
    public Map<String,Object> getPadUserStatus(AppFaceRecognitionPaymentDTO paymentDTO) throws ParseException {
        Map<String,Object> result = new HashMap<>();
        paymentDTO.setDeviceUnique(String.format("%s%s%s", paymentDTO.getProjectId(), paymentDTO.getType(), paymentDTO.getDeviceUnique()));
        paymentDTO.setType(paymentDTO.getType().equals("1") ? "2" : "1");
        List<PropertyValueDeployPO> deploys = iAppRegisterDao.getDeploys(paymentDTO.getProjectId(),paymentDTO.getType());
        if(deploys == null || deploys.isEmpty()){
            result.put("arearageStatus",0);
            return result;
            //未开启物业增值
        }else{
            //获取当前设备的楼栋编号
            Map<String,Object> address = iAppRegisterDao.getDeviceAddressByDeviceUnique(paymentDTO.getDeviceUnique(),paymentDTO.getType());
            //查询当前楼栋的欠费房间及欠费时间
            if(address!=null){
                String buildIds = StringHandlerUtil.getNullOrStringForObject(address.get("buildId"));
                String unitIds = StringHandlerUtil.getNullOrStringForObject(address.get("unitId"));
                String[] buildArr = StringHandlerUtil.splitString(buildIds);
                String[] unitIArr = StringHandlerUtil.splitString(unitIds);
                //获取欠费房间的时间
                String arrearTime = iAppRegisterDao.getArrearageTime(paymentDTO.getProjectId(),paymentDTO.getUId(),buildArr,unitIArr.length > 0 ? unitIArr : null);
                //查询当前楼栋下欠费的房间及欠费的天数及不欠费的房间数
                Map<String,Object> roomInfo = iAppRegisterDao.getArrearRoomInfo(paymentDTO.getProjectId(),paymentDTO.getUId(),buildArr,unitIArr.length > 0 ? unitIArr : null,arrearTime);
                if(roomInfo != null ){
                    //计算欠费时间
                    Date time = DateUtil.formatStringToDate(roomInfo.get("month").toString(),"yyyy-MM-dd");
                    time = DateUtil.getAddMonth(time,1);
                    time = roomInfo.get("feeDay").toString().equals("1") ? time : DateUtil.getAddDay(time,Integer.valueOf(roomInfo.get("feeDay").toString())-1);
                    //计算当前欠费了多少天
                    Integer day = Integer.valueOf(DateUtil.reckonDate(DateUtil.fomatDate(new Date(),"yyyy-MM-dd HH:mm:ss"),DateUtil.fomatDate(time,"yyyy-MM-dd HH:mm:ss")).get("day").toString());
                    //未欠费的房间数
                    String noArrears = StringHandlerUtil.getNullOrStringForObject(roomInfo.get("noArrears"));
                    //判断当前房间的欠费天数
                    for(PropertyValueDeployPO deploy : deploys){
                        if(deploy.getLevel() == 3 || deploy.getLevel() == 2){
                            if(paymentDTO.getType().equals("2")){
                                if(StringUtils.isNotBlank(deploy.getElevatorDeployLimit())&&day>deploy.getDay()){
                                    if(StringUtils.isNotBlank(noArrears) && Integer.valueOf(noArrears) > 0){
                                        //如果有欠费房间，返回提示信息不限制通行
                                        result.put("arearageStatus",8);
                                        return result;
                                    }else{
                                        result.put("arearageStatus",7);
                                        return result;
                                    }
                                }
                            }else{
                                if(StringUtils.isNotBlank(deploy.getEntranceDeployLimit())&&day>deploy.getDay()){
                                    if(StringUtils.isNotBlank(noArrears) && Integer.valueOf(noArrears) > 0){
                                        //如果有欠费房间，返回提示信息不限制通行
                                        result.put("arearageStatus",8);
                                        return result;
                                    }else{
                                        result.put("arearageStatus",7);
                                        return result;
                                    }
                                }
                            }
                        }else if(deploy.getLevel() ==1){
                            if(deploy.getPointOut()!=null && deploy.getPointOut() == 1 && day > deploy.getDay()){
                                result.put("arearageStatus",8);
                                return result;
                            }else{
                                result.put("arearageStatus",0);
                                return result;
                            }
                        }
                    }
                }else{
                    //没有欠费的账单及房间
                    result.put("arearageStatus",0);
                    return result;
                }
            }
        }
        result.put("arearageStatus",0);
        return result;
    }

    /**
     * <desc>
     *     APP端用户缓存丢失后备用查询缓存用户
     * </desc>
     * @param userId
     * @param token
     * @return
     * @author cuiduanwu
     * @createDate 2018/2/5
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public  AppUserCacheVO  resetUserLogin(String userId,String token) {
        try {
            Date current = new Date();
            AppUserInfoPO userInfoPO = new AppUserInfoPO(userId);
            AppUserInfoPO appUserInfoPO = iAppRegisterDao.getOne(userInfoPO);
            if (appUserInfoPO == null||!token.equals(appUserInfoPO.getToken())){
                return  null;
            }else {
                if (DateUtil.daysOfTwo(appUserInfoPO.getUpdateTime(),current)>=7){
                    return null;
                }
                AppUserCacheVO appUserCacheVO = new AppUserCacheVO();
                appUserCacheVO.setId(appUserInfoPO.getId());
                appUserCacheVO.setLoginDevice(appUserInfoPO.getLoginDevice()+"");
                appUserCacheVO.setUserId(appUserInfoPO.getUserId());
                appUserCacheVO.setPhotoUrl(appUserInfoPO.getIcon());
                appUserCacheVO.setNickName(appUserInfoPO.getNickName());
                appUserCacheVO.setUserName(appUserInfoPO.getRealName());
                appUserCacheVO.setEmail(appUserInfoPO.getEmail());
                if (StringUtils.isNotBlank(appUserInfoPO.getEmail())){
                    appUserCacheVO.setPhoneNo(appUserInfoPO.getEmail());
                }else {
                    appUserCacheVO.setPhoneNo(appUserInfoPO.getPhoneNum());
                }
                appUserCacheVO.setToken(appUserInfoPO.getToken());
                appUserCacheVO.setSex(appUserInfoPO.getGender()+"");
                appUserCacheVO.setCurrentProjectId(appUserInfoPO.getCurrentProjectId());
                appUserCacheVO.setCurrentProjectName(appUserInfoPO.getCurrentProjectName());
                appUserCacheVO.setStatus(appUserInfoPO.getStatus());
                appUserCacheVO.setUuid(appUserInfoPO.getUuid());
                if (StringUtils.isBlank(appUserInfoPO.getPhoneNum())) {
                    appUserCacheVO.setGuestType("1");
                }

                if (!"1".equals(appUserCacheVO.getGuestType())) {
                    List<AppUserOwnProjectVO> userOwnProjectList = this.getUserOwnProjectsInfo(userId,"-1");
                    appUserCacheVO.setProjects(userOwnProjectList);
                    if (userOwnProjectList != null&&userOwnProjectList.size()>0){ //未申请房屋认证审核通过或者全部房间均被迁出
                        if (StringUtils.isBlank(appUserCacheVO.getCurrentProjectId())||StringUtils.isBlank(appUserCacheVO.getCurrentProjectName())){
                            appUserCacheVO.setCurrentProjectId(userOwnProjectList.get(0).getProjectId());
                            appUserCacheVO.setCurrentProjectName(userOwnProjectList.get(0).getProjectName());
                        }
                    }else {
                        appUserCacheVO.setCurrentProjectId("");
                        appUserCacheVO.setCurrentProjectName("");
                    }
                } else {
                    List<AppUserOwnProjectVO> projects = new ArrayList<>();
                    if (StringUtils.isNotBlank(appUserCacheVO.getCurrentProjectId())) {
                        AppUserOwnProjectVO appUserOwnProjectVO = iAppRegisterDao.getTouristProject(appUserCacheVO.getCurrentProjectId());
                        if (appUserOwnProjectVO != null && StringUtils.isNotBlank(appUserOwnProjectVO.getProjectId())) {
                            appUserOwnProjectVO.setState("0");
                            appUserOwnProjectVO.setUserAuth("0");
                            appUserOwnProjectVO.setProjectProperties("1");
                            appUserOwnProjectVO = (AppUserOwnProjectVO) StringHandlerUtil.formatString(appUserOwnProjectVO);
                            projects.add(appUserOwnProjectVO);
                        }
                    }
                    appUserCacheVO.setProjects(projects);
                }
                appUserCacheVO = (AppUserCacheVO)StringHandlerUtil.formatString(appUserCacheVO);
                boolean flag = redisService.set(RedisConstant.APP_LOGIN+appUserCacheVO.getUserId(),RedisConstant.APP_USER_TOKEN_TIME,appUserCacheVO);
                userInfoPO.setUpdateTime(current);
                iAppRegisterDao.updateByPoNotNull(userInfoPO);

                return  appUserCacheVO;
            }
        }catch (Exception e){
            LOG.error("【APP端用户缓存丢失后备用查询缓存用户】当前时间：" + DateUtil.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss:"),e);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer getAppUserStatusByUserId(String userId){
        return iAppRegisterDao.getAppUserStatusByUserId(userId);
    }

    /**
     * <desc>
     *     检查当前账号是否被锁定
     * </desc>
     * @param phoneNo 手机号
     * @return
     * @author Juguang.S
     * @createDate 2018/10/16
     */
    @Override
    public MessageVO getAppAccountLockDetail(String phoneNo) {
        try {

            Map<String, Object> params = new HashMap<>();
            params.put("phoneNo", phoneNo);
            List<AppUserInfoPO> userPOs = iAppRegisterDao.getByFields(params);
            if (userPOs ==null || userPOs.isEmpty()) {
                return null;
            }
            AppUserInfoPO userInfoPO=userPOs.get(0);

            String lockUserNameKey = String.format("%s%s", RedisConstant.APP_LOGIN_ERROR_REDIS_KEY, userInfoPO.getUserId());
            AppLoginErrorCacheVO errorCacheVO = loginErrorRedisService.getObject(lockUserNameKey, AppLoginErrorCacheVO.class);
            Map<String,Object> result = new HashMap<>();
            if (errorCacheVO != null) {

                //计算当前时间和锁定时间，如果小于规定的锁定时间，返回相应提示信息
                String lockTimeStr = errorCacheVO.getLockTime();
                if (StringUtils.isNotEmpty(lockTimeStr)) {
                    Date lockTime = new SimpleDateFormat(dateFormatStr).parse(lockTimeStr);
                    long distanceTime = (new Date().getTime() - lockTime.getTime()) / 1000;
                    Long lockLimitTime = PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME;
                    if (distanceTime < lockLimitTime) {
                        //在锁定时间内：返回锁定时间信息
                        result.put("remainTime",((lockLimitTime - distanceTime) / 60) + 1);
                        AppUserCacheVO cacheVO = new AppUserCacheVO();
                        cacheVO.setRemainTime(((lockLimitTime - distanceTime) / 60) + 1);
                        return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), cacheVO);
                    } else {
                        //锁定时间已过，清空该账号的错误缓存数据
                        loginErrorRedisService.del(lockUserNameKey);
                    }
                }
            }
            return null;
        } catch (ParseException e) {
            throw new DataAccessException("【App_getAppAccountLockDetail】检查账号是否被锁定异常", e);
        }
    }

    /**
     * <desc>
     *      App登录错误处理
     * <desc/>
     * @param   phoneNo    手机号
     * @return  标准化响应结果
     * @author Juguang.S
     * @createDate 2018/10/16
     */
    @Override
    public MessageVO loginErrorHandler(String phoneNo,String language) {
        Map<String, Object> params = new HashMap<>();
        params.put("phoneNo", phoneNo);
        List<AppUserInfoPO> userPOs = iAppRegisterDao.getByFields(params);
        if (userPOs == null || userPOs.isEmpty()) {
            return new MessageVO(LanguageTypeEnum.CHINESE.getLanguage().equals(language) ?
                    AppErrorCodeEnum.ACCOUNT_NOT_EXIST_ERR.getErrorCode() : AppErrorCodeEnumEN.ACCOUNT_NOT_EXIST_ERR.getErrorCode());
        }
        String userId = userPOs.get(0).getUserId();

        //最大输入次数
        Integer limitErrorCount = PlatformConstants.OPERATE_LOGIN_MAX_ERROR_COUNT;
        Map<String, Object> result = new HashMap<>();
        String errorCacheKey = String.format("%s%s", RedisConstant.APP_LOGIN_ERROR_REDIS_KEY, userId);
        AppLoginErrorCacheVO errorCacheVO = loginErrorRedisService.getObject(errorCacheKey, AppLoginErrorCacheVO.class);

        if (errorCacheVO == null) {
            //如果该账号之前没有输入错误，添加登陆错误缓存信息，记录输错次数
            errorCacheVO = new AppLoginErrorCacheVO(phoneNo,userId, 1);
            loginErrorRedisService.set(errorCacheKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
            result.put("errorCount", limitErrorCount - 1);
            AppUserCacheVO cacheVO = new AppUserCacheVO();
            cacheVO.setErrorCount(limitErrorCount - 1);
            return new MessageVO(LanguageTypeEnum.CHINESE.getLanguage().equals(language) ?
                    PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode() : AppErrorCodeEnumEN.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), cacheVO);
        } else {

            //查询已经错误的次数：如果次数大于5，锁定30分钟
            Integer errorCount = errorCacheVO.getErrorCount();
            if (errorCount + 1 >= limitErrorCount) {

                //生成账号锁定缓存信息
                String lockUserNameKey = String.format("%s%s", RedisConstant.APP_LOGIN_ERROR_REDIS_KEY, userId);
                errorCacheVO = new AppLoginErrorCacheVO(phoneNo,userId, errorCount);
                errorCacheVO.setLockTime(new SimpleDateFormat(dateFormatStr).format(new Date()));
                loginErrorRedisService.set(lockUserNameKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("remainTime", PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME / 60);
                AppUserCacheVO cacheVO = new AppUserCacheVO();
                cacheVO.setRemainTime(PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME / 60);
                return new MessageVO(LanguageTypeEnum.CHINESE.getLanguage().equals(language) ?
                        PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode() : AppErrorCodeEnumEN.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), cacheVO);
            } else {

                //输错次数小于5次，更新缓存信息，并给出相应提示
                errorCacheVO = new AppLoginErrorCacheVO(phoneNo,userId, errorCount + 1);
                loginErrorRedisService.set(errorCacheKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("errorCount", limitErrorCount - errorCount - 1);
                AppUserCacheVO cacheVO = new AppUserCacheVO();
                cacheVO.setErrorCount(limitErrorCount - errorCount - 1);
                return new MessageVO(LanguageTypeEnum.CHINESE.getLanguage().equals(language) ?
                        PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode() : AppErrorCodeEnumEN.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), cacheVO);
            }
        }
    }


    /**
     * <desc>
     *      APP端登录根据用户ID与项目编号获取房间总数或业主房间总数
     * </desc>
     *
     * @param userId 用户id
     * @param projectId 项目id
     * @return
     * @throws Exception
     * @createDate 2017/9/28
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer countUserAttacheInfoInProject(String userId,String projectId){
        Map<String,Object> params=new HashMap<>();
        params.put("userId",userId);
        params.put("projectId",projectId);
        return iAppRegisterDao.countUserAttacheInfoInProject(params);
    }


    /**
     * <desc>
     *      通过userid获取用户基本信息
     * </desc>
     * @param userId 用户id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/12/22
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public AppUserInfoPO getBaseUserInfo(String userId){
        return iAppRegisterDao.getBaseUserInfo(userId);
    }


    /**
     * <desc>
     *     根据APP端用户的操作日志来自动更新用户Token缓存
     * </desc>
     * @return
     * @author cuiduanwu
     * @createDate 2018/1/18
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean timeTaskOfUserTokenUpdate() throws Exception{
        try {
            List<AppUserInfoPO> operateAppUserList = iAppRegisterDao.getOperateAppUser();
            if (operateAppUserList != null&&operateAppUserList.size()>0){
                for (AppUserInfoPO appuser:operateAppUserList){
                    String userId = appuser.getUserId();
                    AppUserCacheVO appUserCacheVO = new AppUserCacheVO(appuser.getId(),userId,appuser.getRealName(),appuser.getNickName(),appuser.getPhoneNum(),appuser.getEmail(),
                            appuser.getIcon(),appuser.getGender()+"",appuser.getToken(),appuser.getLoginDevice()+"",appuser.getCurrentProjectId(),appuser.getCurrentProjectName(),appuser.getStatus(),appuser.getUuid());
                    if (StringUtils.isNotBlank(appuser.getEmail())){
                        appUserCacheVO.setPhoneNo(appuser.getEmail());
                    }
                    List<AppUserOwnProjectVO> userOwnProjectList = iAppRegisterDao.getUserOwnProjectsInfo(userId);
                    if (userOwnProjectList != null&&userOwnProjectList.size()>0){ //未申请房屋认证审核通过或者全部房间均被迁出
                        if (StringUtils.isBlank(appUserCacheVO.getCurrentProjectId())||StringUtils.isBlank(appUserCacheVO.getCurrentProjectName())){
                            appUserCacheVO.setCurrentProjectId(userOwnProjectList.get(0).getProjectId());
                            appUserCacheVO.setCurrentProjectName(userOwnProjectList.get(0).getProjectName());
                        }
                    }else {
                        appUserCacheVO.setCurrentProjectId("");
                        appUserCacheVO.setCurrentProjectName("");
                    }
                    appUserCacheVO.setProjects(userOwnProjectList);

                    boolean flag = redisService.set(RedisConstant.APP_LOGIN+appUserCacheVO.getUserId(),RedisConstant.APP_USER_TOKEN_TIME,appUserCacheVO);
                    if (!flag){
                        LOG.info("【定时任务】自动更新用户Token缓存执行失败，当前时间：" + DateUtil.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss:")+"--userId:"+appUserCacheVO.getUserId()+"-phoneNo or Email:"+appUserCacheVO.getPhoneNo()+"-"+appUserCacheVO.getEmail());
                    }
                }
            }
        }catch (Exception e){
            LOG.error("【定时任务】根据APP端用户的操作日志更新用户Token缓存执行失败，当前时间：" + DateUtil.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss:"),e);
            throw   new Exception("【定时任务】根据APP端用户的操作日志更新用户Token缓存执行失败");
        }
        return  true;
    }

    /**
     * <desc>
     *     根据userId查询当前用户是否有人脸
     * </desc>
     * @return
     * @author Juguang.S
     * @createDate 2018/4/24
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer getIsFace(String userId){
        return iAppRegisterDao.getIsFace(userId);
    }

    /**
     * <desc>
     *     根据cardId查询当前用户
     * </desc>
     * @return
     * @author Juguang.S
     * @createDate 2018/4/24
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getCardUserId(String cardId){
        return iAppRegisterDao.getCardUserId(cardId);
    }

    /**
     * <desc>
     *      获取用户的第三方账号信息
     * </desc>
     *
     * @param cloudIntercomAccountId 第三方提供账号表的逻辑主键
     * @return 第三方账号信息
     * @author wangzhi
     * @createDate 2018/07/17
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public CloudIntercomAccountInfoPO getClientAccount(String cloudIntercomAccountId) {
        return iAppRegisterDao.getClientAccount(cloudIntercomAccountId);
    }

    /**
     * <desc>
     *      获取用户消息状态和欠费房间id
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId 用户id
     * @return 用户消息状态和欠费房间id
     * @author wangzhi
     * @createDate 2019/05/29
     */
    @Override
    public AppUserCacheVO getUserMsgAndRoomId(String projectId, String userId, String version) throws Exception {
        Date nowTime = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE1);
        LOG.info("生成缴费通知信息项目id：" + projectId + "，用户id" + userId + "，用来保存的nowTime：" + sdf.format(nowTime));
        // 当到这一步时，先去构造符合条件的缴费通知添加到数据库
        List<PropertyPaymentVO> billList = iAppRegisterDao.getUnpaidBill(projectId, userId);
        LOG.info("未缴账单信息：" + billList);
        if (billList != null && !billList.isEmpty()) {
            List<PropertyInfoPO> propertyInfoPOList = new ArrayList<>();
            for (PropertyPaymentVO propertyPaymentVO : billList) {
                // 校验该feeId是否已经存在消息，如果存在，则不创建
                String feeUpdateTime = iAppRegisterDao.getPropertyInfoFeeTimeByFeeId(propertyPaymentVO.getFeeId());
                LOG.info("已生成的该账单缴费通知最后更新时间feeUpdateTime：" + feeUpdateTime + "，该账单最后更新时间：" + propertyPaymentVO.getEndTime());
                if (propertyPaymentVO.getEndTime().equals(feeUpdateTime)) {
                    continue;
                }
                // 缴费通知发送给房间下所有住户，通过房间查询所有住户
                List<String> roomUserIdList = iAppRegisterDao.getUserIdByRoomId(propertyPaymentVO.getPhoneNum());
                //LOG.info("房间" + propertyPaymentVO.getPhoneNum() + "的住户userId列表：" + roomUserIdList);
                for (String roomUserId : roomUserIdList) {
                    PropertyInfoPO propertyInfoPO = new PropertyInfoPO();
                    propertyInfoPO.setPropertyInfoId(LogicIdUtil.bussinessId());
                    propertyInfoPO.setProjectId(projectId);
                    propertyInfoPO.setPropertyType(5);
                    propertyInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
                    propertyInfoPO.setTitle(propertyPaymentVO.getMonth() + "月份物业缴费通知");
                    propertyInfoPO.setPropertyInfo("您有1笔物业费" + propertyPaymentVO.getPaidAmount() + "元待缴纳，点击查看详情和支付，感谢您对我们工作的支持，祝生活愉快！");
                    propertyInfoPO.setReceiver(roomUserId);
                    propertyInfoPO.setCreateTime(nowTime);
                    propertyInfoPO.setUpdateTime(nowTime);
                    propertyInfoPO.setReadStatus(0);
                    propertyInfoPO.setUrl("");
                    propertyInfoPO.setFeeId(propertyPaymentVO.getFeeId());
                    propertyInfoPO.setFeeUpdateTime(sdf.parse(propertyPaymentVO.getEndTime()));
                    propertyInfoPOList.add(propertyInfoPO);
                }
            }
            //LOG.info("待保存缴费通知列表：" + propertyInfoPOList);
            if (!propertyInfoPOList.isEmpty()) {
                iAppRegisterDao.batchSavePropertyInfo(propertyInfoPOList);
            }
        }
        AppUserCacheVO appUserCacheVO = new AppUserCacheVO();
        int count = iAppRegisterDao.getPropertyInfoCountOfUser(projectId, userId);
        // 1.8.5版本先注掉，1.8.6合并代码后打开注释
        // 获取未读的小区通知和系统消息数量
        count += iAppRegisterDao.getAllUnreadPushInfoCount(projectId, userId, version);
        appUserCacheVO.setHasNewMsg(count > 0 ? "1" : "0");
        // 查询欠费房间号，应APP要求，每次只返回一个
        String roomId = iAppRegisterDao.getArrearRoomId(projectId, userId);
        appUserCacheVO.setRoomId(roomId == null ? "" : roomId);
        return appUserCacheVO;
    }

    /**
     * <desc>
     *      根据userId 登录密码校验密码的正确性
     * </desc>
     *
     * @param userId 用户id
     * @param loginPwd 登录密码
     * @return
     * @throws Exception
     * @createDate 2019/9/17
     */
    @Override
    public Integer checkLoginPwd(String userId,String loginPwd){
        return iAppRegisterDao.checkLoginPwd(userId,loginPwd);
    }

    /**
     * <desc>
     *      游客登录
     * </desc>
     *
     * @return 登录信息
     * @author wangzhi
     * @createDate 2020/04/30
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Map<String, Object> touristLogin(AppTouristDTO appTouristDTO) throws Exception {
        Map<String, Object> data = new HashMap<>();
        SimpleDateFormat df = new SimpleDateFormat("MMddHHmmss");
        Date nowTime = new Date();
        String time = df.format(nowTime);
        String token;
        // 先通过uuid获取该设备游客用户
        AppUserInfoPO touristUser = iAppRegisterDao.getTouristUser(appTouristDTO.getUuid());
        if (touristUser == null || StringUtils.isBlank(touristUser.getUserId())) {
            // 该游客未创建用户信息，先创建信息后登录
            touristUser = new AppUserInfoPO();
            touristUser.setUserId(LogicIdUtil.userBusinessId());
            touristUser.setUuid(appTouristDTO.getUuid());
            touristUser.setPhoneUnique(appTouristDTO.getUuid());
            token = UserTokenUtil.tokenEncrypt(touristUser.getUserId() + time, appTouristDTO.getTokenKey(), SystemTypeEnum.IOS.getType());
            touristUser.setToken(token);
            touristUser.setLoginDevice(Integer.parseInt(appTouristDTO.getLoginDevice()));
            touristUser.setStatus(DataStatusEnum.NORMAL.getType());
            touristUser.setCreateTime(nowTime);
            touristUser.setUpdateTime(nowTime);
            iAppRegisterDao.save(SqlUtil.durableData(touristUser, PlatformConstants.TABLE_SAVE));
        } else {
            // 该游客已创建用户信息，更新相关字段
            touristUser.setUuid(appTouristDTO.getUuid());
            // 判断该游客是否已登录，缓存还在的情况下不生成新token，防止app频繁刷新请求游客登录接口时token频繁变化而导致调用其它接口返回登录过期
            AppUserCacheVO userInfo = redisService.getObject(RedisConstant.APP_LOGIN + touristUser.getUserId(), AppUserCacheVO.class);
            if (userInfo != null) {
                token = userInfo.getToken();
            } else {
                token = UserTokenUtil.tokenEncrypt(touristUser.getUserId() + time, appTouristDTO.getTokenKey(), SystemTypeEnum.IOS.getType());
            }
            touristUser.setToken(token);
            touristUser.setLoginDevice(Integer.parseInt(appTouristDTO.getLoginDevice()));
            touristUser.setUpdateTime(nowTime);
            iAppRegisterDao.updateByPoNotNull(touristUser);
        }

        // 根据定位获取最近项目，1km内
        Map<String, Object> projectByPosition = getProjectByPosition(appTouristDTO.getPosition());

        data.put("token", token);
        AppUserCacheVO appUserCacheVO = new AppUserCacheVO();
        appUserCacheVO.setId(touristUser.getId());
        appUserCacheVO.setLoginDevice(appTouristDTO.getLoginDevice());
        appUserCacheVO.setUserId(touristUser.getUserId());
        appUserCacheVO.setPhotoUrl("");
        appUserCacheVO.setNickName("");
        appUserCacheVO.setUserName("");
        appUserCacheVO.setPhoneNo("");
        appUserCacheVO.setToken(token);
        appUserCacheVO.setSex("");
        appUserCacheVO.setUuid(appTouristDTO.getUuid());
        appUserCacheVO.setCurrentProjectId(projectByPosition.get("projectId").toString());
        appUserCacheVO.setCurrentProjectName(projectByPosition.get("projectName").toString());
        List<AppUserOwnProjectVO> projects = new ArrayList<>();
        if (StringUtils.isNotBlank(appUserCacheVO.getCurrentProjectId())) {
            AppUserOwnProjectVO appUserOwnProjectVO = iAppRegisterDao.getTouristProject(appUserCacheVO.getCurrentProjectId());
            if (appUserOwnProjectVO != null && StringUtils.isNotBlank(appUserOwnProjectVO.getProjectId())) {
                appUserOwnProjectVO.setState("0");
                appUserOwnProjectVO.setUserAuth("0");
                appUserOwnProjectVO.setProjectProperties("1");
                appUserOwnProjectVO = (AppUserOwnProjectVO) StringHandlerUtil.formatString(appUserOwnProjectVO);
                projects.add(appUserOwnProjectVO);
            }
        }
        appUserCacheVO.setProjects(projects);
        appUserCacheVO.setStatus(touristUser.getStatus());
        appUserCacheVO.setForbidden("0");
        appUserCacheVO.setHasNewMsg("0");
        appUserCacheVO.setRoomId("");
        appUserCacheVO.setGuestType("1");
        redisService.set(RedisConstant.APP_LOGIN + appUserCacheVO.getUserId(), RedisConstant.APP_TOURIST_USER_TOKEN_TIME, appUserCacheVO);

        // 保存游客项目历史数据
        if (StringUtils.isNotBlank(appUserCacheVO.getCurrentProjectId())) {
            GuestUserHistoryPO guestUserHistoryPO = iAppRegisterDao.getGuestUserProject(touristUser.getUserId(), appUserCacheVO.getCurrentProjectId());
            // 有则修改，无则新增
            if (guestUserHistoryPO == null || StringUtils.isBlank(guestUserHistoryPO.getUserId())) {
                // 新增
                guestUserHistoryPO = new GuestUserHistoryPO();
                guestUserHistoryPO.setUserId(touristUser.getUserId());
                guestUserHistoryPO.setProjectId(appUserCacheVO.getCurrentProjectId());
                guestUserHistoryPO.setSource(1);
                guestUserHistoryPO.setCreateUserId(touristUser.getUserId());
                guestUserHistoryPO.setOperateUserId(touristUser.getUserId());
                guestUserHistoryPO.setStatus(DataStatusEnum.NORMAL.getType());
                guestUserHistoryPO.setCreateTime(nowTime);
                guestUserHistoryPO.setUpdateTime(nowTime);
                iAppRegisterDao.save(SqlUtil.durableData(guestUserHistoryPO, PlatformConstants.TABLE_SAVE));
            } else {
                // 修改
                guestUserHistoryPO.setUserId(touristUser.getUserId());
                guestUserHistoryPO.setProjectId(appUserCacheVO.getCurrentProjectId());
                guestUserHistoryPO.setOperateUserId(touristUser.getUserId());
                guestUserHistoryPO.setUpdateTime(nowTime);
                iAppRegisterDao.updateGuestUserProject(guestUserHistoryPO);
            }
        }

        data.put("currentProjectId", appUserCacheVO.getCurrentProjectId());
        data.put("currentProjectName", appUserCacheVO.getCurrentProjectName());
        return data;
    }

    /**
     * <desc>
     *      获取游客项目信息
     * </desc>
     *
     * @return 游客项目信息
     * @author wangzhi
     * @createDate 2020/05/18
     */
    @Override
    public AppUserOwnProjectVO getGuestProject(String projectId) throws Exception {
        AppUserOwnProjectVO appUserOwnProjectVO = iAppRegisterDao.getTouristProject(projectId);
        if (appUserOwnProjectVO != null && StringUtils.isNotBlank(appUserOwnProjectVO.getProjectId())) {
            Map<String, Integer> sceneIdMap = getSceneTypeMap();
            appUserOwnProjectVO.setProjectType(sceneIdMap.get(appUserOwnProjectVO.getSceneId()));
            appUserOwnProjectVO.setState("0");
            appUserOwnProjectVO.setUserAuth("0");
            appUserOwnProjectVO.setProjectProperties("1");
            appUserOwnProjectVO = (AppUserOwnProjectVO) StringHandlerUtil.formatString(appUserOwnProjectVO);
        }
        return appUserOwnProjectVO;
    }

    /**
     * <desc>
     *      保存游客项目历史信息
     * </desc>
     *
     * @return 受影响行数
     * @author wangzhi
     * @createDate 2020/05/12
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer saveOrUpdateGuestProject(GuestUserHistoryPO guestUserHistoryPO) throws Exception {
        Date nowTime = new Date();
        GuestUserHistoryPO guestUserHistoryPOData = iAppRegisterDao.getGuestUserProject(guestUserHistoryPO.getUserId(), guestUserHistoryPO.getProjectId());
        // 有则修改，无则新增
        if (guestUserHistoryPOData == null || StringUtils.isBlank(guestUserHistoryPOData.getUserId())) {
            // 新增
            guestUserHistoryPO.setCreateUserId(guestUserHistoryPO.getUserId());
            guestUserHistoryPO.setOperateUserId(guestUserHistoryPO.getUserId());
            guestUserHistoryPO.setStatus(DataStatusEnum.NORMAL.getType());
            guestUserHistoryPO.setCreateTime(nowTime);
            guestUserHistoryPO.setUpdateTime(nowTime);
            iAppRegisterDao.save(SqlUtil.durableData(guestUserHistoryPO, PlatformConstants.TABLE_SAVE));
        } else {
            // 修改
            guestUserHistoryPO.setOperateUserId(guestUserHistoryPO.getUserId());
            guestUserHistoryPO.setUpdateTime(nowTime);
            iAppRegisterDao.updateGuestUserProject(guestUserHistoryPO);
        }
        return 1;
    }

    /**
     * <desc>
     *      根据定位获取最近项目，1km内
     * </desc>
     *
     * @return 项目信息
     * @author wangzhi
     * @createDate 2020/04/30
     */
    private Map<String, Object> getProjectByPosition(String position) throws Exception {
        List<String> positionList = StringHandlerUtil.splitStringList(position);
        String longitude = positionList.get(0);
        String latitude = positionList.get(1);
        List<Map<String, Object>> positionMapList = iAppRegisterDao.getAllProjectHasPosition();
        Map<String, Object> data = new HashMap<>();
        if (positionMapList != null && !positionMapList.isEmpty()) {
            double lng1 = Double.parseDouble(longitude);
            double lat1 = Double.parseDouble(latitude);
            for (Map<String, Object> positionMap : positionMapList) {
                String positionData = positionMap.get("position").toString();
                if (StringUtils.isBlank(positionData)) {
                    continue;
                }
                String[] positionArr = StringHandlerUtil.splitString(positionData);
                if (positionArr.length != 2) {
                    continue;
                }
                double lng2 = Double.parseDouble(positionArr[0]);
                double lat2 = Double.parseDouble(positionArr[1]);
                // 计算两点直线距离
                double distance = LocationUtil.getDistance(lat1, lng1, lat2, lng2);
                // 满足小于1km，且data中没有值或比data中的小区距离更近，则替换
                if (distance < 1000 && (data.isEmpty() || distance < Double.parseDouble(data.get("distance").toString()))) {
                    data.put("projectId", positionMap.get("projectId"));
                    data.put("projectName", positionMap.get("projectName"));
                    data.put("distance", distance);
                }
            }
        }
        data.remove("distance");
        if (data.get("projectId") == null) {
            data.put("projectId", "");
            data.put("projectName", "");
        }
        return data;
    }

    /**
     * <desc>
     *      查询用户在项目下是否被禁用
     * </desc>
     *
     * @param userId 用户id
     * @param projectId 项目id
     * @return
     * @throws Exception
     * @createDate 2020/11/23
     */
    public Integer getUserStatusByProjectId(String userId,String projectId){
        return iAppRegisterDao.getUserStatusByProjectId(userId,projectId);
    }

    /**
     * <desc>
     *      获取场景类型map集合
     * </desc>
     *
     * @param
     * @return
     * @Author Zhu.yj
     * @createDate  2021/4/6
     */
    private Map<String, Integer> getSceneTypeMap(){
        Map<String, Integer> sceneMap=  new HashMap<>();
        sceneMap.put(communitySceneId, SceneTypeEnum.COMMUNITY_SCENE.getType());
        sceneMap.put(parkScene, SceneTypeEnum.PARK_SCENE.getType());
        sceneMap.put(hotelSceneId, SceneTypeEnum.HOTEL_SCENE.getType());
        sceneMap.put(hospitalSceneId, SceneTypeEnum.HOSPITAL_SCENE.getType());
        return sceneMap;
    }
}
